React λ λ νλ‘ ν¨ν΄μ κ°λ ₯ν κΈ°λ₯μ μμ보μΈμ. μ½λ μ¬μ¬μ©μ±, μ»΄ν¬λνΈ κ΅¬μ±, κ΄μ¬μ¬ λΆλ¦¬λ₯Ό ν΅ν΄ κΈλ‘λ² μ¬μ©μλ₯Ό μν μ μ°νκ³ μ μ§λ³΄μ κ°λ₯ν μ ν리μΌμ΄μ κ΅¬μΆ λ°©λ²μ λ°°μλλ€.
React λ λ νλ‘(Render Props) ν¨ν΄: κΈλ‘λ² μ¬μ©μλ₯Ό μν μ μ°ν μ»΄ν¬λνΈ λ‘μ§
λμμμ΄ μ§ννλ νλ‘ νΈμλ κ°λ° νκ²½, νΉν React μνκ³μμ μν€ν μ² ν¨ν΄μ νμ₯ κ°λ₯νκ³ μ μ§λ³΄μ κ°λ₯νλ©° μ¬μ¬μ© κ°λ₯ν μ»΄ν¬λνΈλ₯Ό ꡬμΆνλ λ° μ€μν μν μ ν©λλ€. μ΄λ¬ν ν¨ν΄ μ€ λ λ νλ‘(Render Props) ν¨ν΄μ React μ»΄ν¬λνΈ κ°μ μ½λμ λ‘μ§μ 곡μ νλ κ°λ ₯ν κΈ°μ λ‘ λ보μ λλ€. μ΄ λΈλ‘κ·Έ κ²μλ¬Όμ λ λ νλ‘ ν¨ν΄μ λν ν¬κ΄μ μΈ μ΄ν΄μ κ·Έ μ΄μ , μ¬μ© μ¬λ‘, κ·Έλ¦¬κ³ μ μΈκ³ μ¬μ©μλ₯Ό μν κ²¬κ³ νκ³ μ μμ± μλ μ ν리μΌμ΄μ μ ꡬμΆνλ λ° μ΄λ»κ² κΈ°μ¬νλμ§ μ 곡νλ κ²μ λͺ©νλ‘ ν©λλ€.
λ λ νλ‘(Render Props)μ΄λ 무μμΈκ°μ?
λ λ νλ‘μ κ°μ΄ ν¨μμΈ propμ μ¬μ©νμ¬ React μ»΄ν¬λνΈ κ°μ μ½λλ₯Ό 곡μ νλ κ°λ¨ν κΈ°μ μ λλ€. λ³Έμ§μ μΌλ‘, λ λ νλ‘μ κ°μ§ μ»΄ν¬λνΈλ React μ리먼νΈλ₯Ό λ°ννλ ν¨μλ₯Ό λ°μ 무μΈκ°λ₯Ό λ λλ§νκΈ° μν΄ μ΄ ν¨μλ₯Ό νΈμΆν©λλ€. μ»΄ν¬λνΈλ 무μμ λ λλ§ν μ§ μ§μ κ²°μ νμ§ μκ³ , κ·Έ κ²°μ μ λ λ νλ‘ ν¨μμ μμνμ¬ λ΄λΆ μνμ λ‘μ§μ μ κ·Όν μ μλλ‘ ν©λλ€.
λ€μ κΈ°λ³Έ μμ λ₯Ό μ΄ν΄λ³΄κ² μ΅λλ€.
class DataProvider extends React.Component {
constructor(props) {
super(props);
this.state = { data: null };
}
componentDidMount() {
// Simulate fetching data
setTimeout(() => {
this.setState({ data: 'Some data from an API' });
}, 1000);
}
render() {
return this.props.render(this.state.data);
}
}
function MyComponent() {
return (
(
{data ? Data: {data}
: Loading...
}
)}
/>
);
}
μ΄ μμ μμ DataProvider
λ λ°μ΄ν°λ₯Ό κ°μ Έμ MyComponent
κ° μ 곡ν render
prop ν¨μμ μ λ¬ν©λλ€. κ·Έλ¬λ©΄ MyComponent
λ μ΄ λ°μ΄ν°λ₯Ό μ¬μ©νμ¬ μ½ν
μΈ λ₯Ό λ λλ§ν©λλ€.
μ λ λ νλ‘μ μ¬μ©ν΄μΌ ν κΉμ?
λ λ νλ‘ ν¨ν΄μ λͺ κ°μ§ μ£Όμ μ΄μ μ μ 곡ν©λλ€.
- μ½λ μ¬μ¬μ©μ±: λ λ νλ‘μ μ¬μ©νλ©΄ μ¬λ¬ μ»΄ν¬λνΈμ κ±Έμ³ λ‘μ§μ μΊ‘μννκ³ μ¬μ¬μ©ν μ μμ΅λλ€. μ½λλ₯Ό 볡μ νλ λμ νΉμ μμ μ μ²λ¦¬νκ³ λ λ νλ‘μ ν΅ν΄ λ‘μ§μ 곡μ νλ μ»΄ν¬λνΈλ₯Ό λ§λ€ μ μμ΅λλ€.
- μ»΄ν¬λνΈ κ΅¬μ±: λ λ νλ‘μ μ¬λ¬ μ»΄ν¬λνΈμ λ€μν κΈ°λ₯μ λ¨μΌ UI μ리먼νΈλ‘ κ²°ν©ν μ μκ² νμ¬ μ»΄ν¬λνΈ κ΅¬μ±μ μ΄μ§ν©λλ€.
- κ΄μ¬μ¬ λΆλ¦¬: λ λ νλ‘μ λ‘μ§μ νλ μ ν μ΄μ μμ λΆλ¦¬νμ¬ κ΄μ¬μ¬λ₯Ό λΆλ¦¬νλ λ° λμμ΄ λ©λλ€. λ λ νλ‘μ μ 곡νλ μ»΄ν¬λνΈλ λ‘μ§μ μ²λ¦¬νκ³ , λ λ νλ‘μ μ¬μ©νλ μ»΄ν¬λνΈλ λ λλ§μ μ²λ¦¬ν©λλ€.
- μ μ°μ±: λ λ νλ‘μ λΉν λ° μλ μ μ°μ±μ μ 곡ν©λλ€. μ»΄ν¬λνΈμ μλΉμκ° λ°μ΄ν°μ λ‘μ§μ΄ *μ΄λ»κ²* λ λλ§λ μ§ μ μ΄νλ―λ‘ μ»΄ν¬λνΈλ λ€μν μ¬μ© μ¬λ‘μ λ§€μ° μ μλ ₯μ΄ λ°μ΄λ©λλ€.
μ€μ μ¬μ© μ¬λ‘ λ° κ΅μ μ μμ
λ λ νλ‘ ν¨ν΄μ λ€μν μλ리μ€μμ μ μ©ν©λλ€. λ€μμ μ μΈκ³ μ¬μ©μλ₯Ό κ³ λ €ν μμμ ν¨κ» μΌλ°μ μΈ μ¬μ© μ¬λ‘μ λλ€.
1. λ§μ°μ€ μΆμ
μΉ νμ΄μ§μμ λ§μ°μ€ μμΉλ₯Ό μΆμ νκ³ μΆλ€κ³ μμν΄ λ³΄μΈμ. λ λ νλ‘μ μ¬μ©νμ¬ μμμκ² λ§μ°μ€ μ’νλ₯Ό μ 곡νλ MouseTracker
μ»΄ν¬λνΈλ₯Ό λ§λ€ μ μμ΅λλ€.
class MouseTracker extends React.Component {
constructor(props) {
super(props);
this.state = { x: 0, y: 0 };
}
handleMouseMove = event => {
this.setState({ x: event.clientX, y: event.clientY });
};
render() {
return (
{this.props.render(this.state)}
);
}
}
function MyComponent() {
return (
(
The mouse position is ({x}, {y})
)}
/>
);
}
μ΄λ κ΅μ νλ μ ν리μΌμ΄μ μ μ½κ² μ μ©ν μ μμ΅λλ€. μλ₯Ό λ€μ΄, μΌλ³Έμ μμ κ°λ€μ΄ μ¬μ©νλ λλ‘μ μ ν리μΌμ΄μ μ μμν΄ λ³΄μΈμ. λ§μ°μ€ μ’νλ₯Ό μ¬μ©νμ¬ λΈλ¬μ νμ μ μ΄ν μ μμ΅λλ€.
(
)}
/>
2. APIμμ λ°μ΄ν° κ°μ Έμ€κΈ°
APIμμ λ°μ΄ν°λ₯Ό κ°μ Έμ€λ κ²μ μΉ κ°λ°μμ μΌλ°μ μΈ μμ μ λλ€. λ λ νλ‘ μ»΄ν¬λνΈλ λ°μ΄ν° κ°μ Έμ€κΈ° λ‘μ§μ μ²λ¦¬νκ³ μμμκ² λ°μ΄ν°λ₯Ό μ 곡ν μ μμ΅λλ€.
class APIFetcher extends React.Component {
constructor(props) {
super(props);
this.state = { data: null, loading: true, error: null };
}
async componentDidMount() {
try {
const response = await fetch(this.props.url);
const data = await response.json();
this.setState({ data: data, loading: false });
} catch (error) {
this.setState({ error: error, loading: false });
}
}
render() {
return this.props.render(this.state);
}
}
function MyComponent() {
return (
{
if (loading) return Loading...
;
if (error) return Error: {error.message}
;
return {JSON.stringify(data, null, 2)}
;
}}
/>
);
}
μ΄λ νμ§νλ λ°μ΄ν°λ₯Ό μ²λ¦¬ν λ νΉν μ μ©ν©λλ€. μλ₯Ό λ€μ΄, λ€λ₯Έ μ§μμ μ¬μ©μμκ² νμ¨μ νμνλ κ²μ μμν΄ λ³΄μΈμ.
{
if (loading) return Loading exchange rates...
;
if (error) return Error fetching exchange rates.
;
return (
{Object.entries(data.rates).map(([currency, rate]) => (
- {currency}: {rate}
))}
);
}}
/>
3. νΌ μ²λ¦¬
νΌ μν λ° μ ν¨μ± κ²μ¬λ₯Ό κ΄λ¦¬νλ κ²μ 볡μ‘ν μ μμ΅λλ€. λ λ νλ‘ μ»΄ν¬λνΈλ νΌ λ‘μ§μ μΊ‘μννκ³ νΌ μνμ νΈλ€λ¬λ₯Ό μμμκ² μ 곡ν μ μμ΅λλ€.
class FormHandler extends React.Component {
constructor(props) {
super(props);
this.state = { value: '', error: null };
}
handleChange = event => {
this.setState({ value: event.target.value });
};
handleSubmit = event => {
event.preventDefault();
if (this.state.value.length < 5) {
this.setState({ error: 'Value must be at least 5 characters long.' });
return;
}
this.setState({ error: null });
this.props.onSubmit(this.state.value);
};
render() {
return this.props.render({
value: this.state.value,
handleChange: this.handleChange,
handleSubmit: this.handleSubmit,
error: this.state.error
});
}
}
function MyComponent() {
return (
alert(`Submitted value: ${value}`)}
render={({ value, handleChange, handleSubmit, error }) => (
)}
/>
);
}
κ΅μ μ£Όμ νμμ λ§κ² νΌ μ ν¨μ± κ²μ¬ κ·μΉμ μ‘°μ νλ κ²μ κ³ λ €ν΄ λ³΄μΈμ. `FormHandler` μ»΄ν¬λνΈλ μΌλ°μ μΈ μνλ₯Ό μ μ§νλ©΄μ, λ λ νλ‘μ λ€λ₯Έ μ§μμ λν νΉμ μ ν¨μ± κ²μ¬ λ° UI λ‘μ§μ μ μν©λλ€.
sendAddressToServer(address)}
render={({ value, handleChange, handleSubmit, error }) => (
)}
/>
4. κΈ°λ₯ νλκ·Έ λ° A/B ν μ€νΈ
λ λ νλ‘μ κΈ°λ₯ νλκ·Έλ₯Ό κ΄λ¦¬νκ³ A/B ν μ€νΈλ₯Ό μννλ λ°μλ μ¬μ©ν μ μμ΅λλ€. λ λ νλ‘ μ»΄ν¬λνΈλ νμ¬ μ¬μ©μ λλ 무μμλ‘ μμ±λ νλκ·Έλ₯Ό κΈ°λ°μΌλ‘ μ΄λ€ λ²μ μ κΈ°λ₯μ λ λλ§ν μ§ κ²°μ ν μ μμ΅λλ€.
class FeatureFlag extends React.Component {
constructor(props) {
super(props);
this.state = { enabled: Math.random() < this.props.probability };
}
render() {
return this.props.render(this.state.enabled);
}
}
function MyComponent() {
return (
{
if (enabled) {
return New Feature!
;
} else {
return Old Feature
;
}
}}
/>
);
}
μ μΈκ³ μ¬μ©μλ₯Ό λμμΌλ‘ A/B ν μ€νΈλ₯Ό μνν λ μΈμ΄, μ§μ λλ κΈ°ν μΈκ΅¬ ν΅κ³ λ°μ΄ν°λ₯Ό κΈ°λ°μΌλ‘ μ¬μ©μλ₯Ό λΆλ₯νλ κ²μ΄ μ€μν©λλ€. `FeatureFlag` μ»΄ν¬λνΈλ μ΄λ€ λ²μ μ κΈ°λ₯μ νμν μ§ κ²°μ ν λ μ΄λ¬ν μμλ₯Ό κ³ λ €νλλ‘ μμ λ μ μμ΅λλ€.
{
return isEnabled ? : ;
}}
/>
λ λ νλ‘μ λμ: κ³ μ°¨ μ»΄ν¬λνΈ(HOC)μ ν (Hook)
λ λ νλ‘μ κ°λ ₯ν ν¨ν΄μ΄μ§λ§ λΉμ·ν κ²°κ³Όλ₯Ό μ»μ μ μλ λμμ μΈ μ κ·Ό λ°©μλ μμ΅λλ€. λ κ°μ§ μΈκΈ° μλ λμμ κ³ μ°¨ μ»΄ν¬λνΈ(HOC)μ ν (Hook)μ λλ€.
κ³ μ°¨ μ»΄ν¬λνΈ(HOC)
κ³ μ°¨ μ»΄ν¬λνΈ(HOC)λ μ»΄ν¬λνΈλ₯Ό μΈμλ‘ λ°μ μλ‘κ³ ν₯μλ μ»΄ν¬λνΈλ₯Ό λ°ννλ ν¨μμ λλ€. HOCλ μΌλ°μ μΌλ‘ κΈ°μ‘΄ μ»΄ν¬λνΈμ κΈ°λ₯μ΄λ λ‘μ§μ μΆκ°νλ λ° μ¬μ©λ©λλ€.
μλ₯Ό λ€μ΄, withMouse
HOCλ μ»΄ν¬λνΈμ λ§μ°μ€ μΆμ κΈ°λ₯μ μ 곡ν μ μμ΅λλ€.
function withMouse(WrappedComponent) {
return class extends React.Component {
constructor(props) {
super(props);
this.state = { x: 0, y: 0 };
}
handleMouseMove = event => {
this.setState({ x: event.clientX, y: event.clientY });
};
render() {
return (
);
}
};
}
function MyComponent(props) {
return (
The mouse position is ({props.mouse.x}, {props.mouse.y})
);
}
const EnhancedComponent = withMouse(MyComponent);
HOCλ μ½λ μ¬μ¬μ©μ μ 곡νμ§λ§, prop μ΄λ¦ μΆ©λμ μΌμΌν¬ μ μκ³ μ»΄ν¬λνΈ κ΅¬μ±μ λ μ΄λ ΅κ² λ§λ€ μ μμΌλ©°, μ΄λ "λνΌ μ§μ₯(wrapper hell)"μΌλ‘ μλ €μ§ νμμ λλ€.
ν (Hook)
React 16.8μ λμ λ React ν (Hook)μ μ»΄ν¬λνΈ κ°μ μν μ μ₯ λ‘μ§μ μ¬μ¬μ©νλ λ μ§μ μ μ΄κ³ ννμ μΈ λ°©λ²μ μ 곡ν©λλ€. ν μ μ¬μ©νλ©΄ ν¨μ μ»΄ν¬λνΈμμ React μν λ° μλͺ μ£ΌκΈ° κΈ°λ₯μ "μ°κ²°(hook into)"ν μ μμ΅λλ€.
useMousePosition
ν
μ μ¬μ©νλ©΄ λ§μ°μ€ μΆμ κΈ°λ₯μ λ€μκ³Ό κ°μ΄ ꡬνν μ μμ΅λλ€.
import { useState, useEffect } from 'react';
function useMousePosition() {
const [mousePosition, setMousePosition] = useState({ x: 0, y: 0 });
useEffect(() => {
function handleMouseMove(event) {
setMousePosition({ x: event.clientX, y: event.clientY });
}
window.addEventListener('mousemove', handleMouseMove);
return () => {
window.removeEventListener('mousemove', handleMouseMove);
};
}, []);
return mousePosition;
}
function MyComponent() {
const mousePosition = useMousePosition();
return (
The mouse position is ({mousePosition.x}, {mousePosition.y})
);
}
ν μ λ λ νλ‘ λ° HOCμ λΉν΄ μν μ μ₯ λ‘μ§μ μ¬μ¬μ©νλ λ κΉ¨λνκ³ κ°κ²°ν λ°©λ²μ μ 곡ν©λλ€. λν μ½λ κ°λ μ±κ³Ό μ μ§λ³΄μμ±μ ν₯μμν΅λλ€.
λ λ νλ‘ vs. ν : μ¬λ°λ₯Έ λꡬ μ ννκΈ°
λ λ νλ‘κ³Ό ν μ¬μ΄μμ κ²°μ νλ κ²μ νλ‘μ νΈμ νΉμ μꡬ μ¬νκ³Ό κ°μΈμ μΈ μ νΈλμ λ°λΌ λ€λ¦ λλ€. λ€μμ μ£Όμ μ°¨μ΄μ μ λν μμ½μ λλ€.
- κ°λ μ±: ν μ μΌλ°μ μΌλ‘ λ μ½κΈ° μ½κ³ κ°κ²°ν μ½λλ₯Ό λ§λλλ€.
- ꡬμ±: ν μ λ μ¬μ΄ μ»΄ν¬λνΈ κ΅¬μ±μ μ©μ΄νκ² νκ³ HOCμ κ΄λ ¨λ "λνΌ μ§μ₯" λ¬Έμ λ₯Ό νΌν©λλ€.
- λ¨μμ±: ν μ νΉν Reactλ₯Ό μ²μ μ νλ κ°λ°μμκ² λ μ΄ν΄νκ³ μ¬μ©νκΈ° μ¬μΈ μ μμ΅λλ€.
- λ κ±°μ μ½λ: λ λ νλ‘μ μ€λλ μ½λλ² μ΄μ€λ₯Ό μ μ§νκ±°λ ν μ μ¬μ©νλλ‘ μ λ°μ΄νΈλμ§ μμ μ»΄ν¬λνΈλ‘ μμ ν λ λ μ ν©ν μ μμ΅λλ€.
- μ μ΄: λ λ νλ‘μ λ λλ§ νλ‘μΈμ€μ λν λ λͺ μμ μΈ μ μ΄λ₯Ό μ 곡ν©λλ€. λ λ νλ‘ μ»΄ν¬λνΈκ° μ 곡νλ λ°μ΄ν°λ₯Ό κΈ°λ°μΌλ‘ μ νν 무μμ λ λλ§ν μ§ κ²°μ ν μ μμ΅λλ€.
λ λ νλ‘ μ¬μ©μ μν λͺ¨λ² μ¬λ‘
λ λ νλ‘ ν¨ν΄μ ν¨κ³Όμ μΌλ‘ μ¬μ©νλ €λ©΄ λ€μ λͺ¨λ² μ¬λ‘λ₯Ό κ³ λ €νμΈμ.
- λ λ νλ‘ ν¨μλ₯Ό λ¨μνκ² μ μ§νκΈ°: λ λ νλ‘ ν¨μλ μ 곡λ λ°μ΄ν°λ₯Ό κΈ°λ°μΌλ‘ UIλ₯Ό λ λλ§νλ λ° μ§μ€νκ³ λ³΅μ‘ν λ‘μ§μ νΌν΄μΌ ν©λλ€.
- μ€λͺ
μ μΈ Prop μ΄λ¦ μ¬μ©νκΈ°: propμ λͺ©μ μ λͺ
ννκ² λνλ΄κΈ° μν΄ μ€λͺ
μ μΈ prop μ΄λ¦(μ:
render
,children
,component
)μ μ ννμΈμ. - λΆνμν 리λ λλ§ νΌνκΈ°: νΉν μμ£Ό λ³κ²½λλ λ°μ΄ν°λ₯Ό μ²λ¦¬ν λ λΆνμν 리λ λλ§μ νΌνκΈ° μν΄ λ λ νλ‘ μ»΄ν¬λνΈλ₯Ό μ΅μ ννμΈμ. propsκ° λ³κ²½λμ§ μμμ λ 리λ λλ§μ λ°©μ§νλ €λ©΄
React.memo
λλshouldComponentUpdate
λ₯Ό μ¬μ©νμΈμ. - μ»΄ν¬λνΈ λ¬ΈμννκΈ°: λ λ νλ‘ μ»΄ν¬λνΈμ λͺ©μ κ³Ό μ¬μ© λ°©λ², μμ λ°μ΄ν° λ° μ¬μ© κ°λ₯ν propsλ₯Ό ν¬ν¨νμ¬ λͺ ννκ² λ¬ΈμννμΈμ.
κ²°λ‘
λ λ νλ‘ ν¨ν΄μ μ μ°νκ³ μ¬μ¬μ© κ°λ₯ν React μ»΄ν¬λνΈλ₯Ό ꡬμΆνκΈ° μν κ·μ€ν κΈ°μ μ λλ€. λ‘μ§μ μΊ‘μννκ³ λ λ νλ‘μ ν΅ν΄ μ»΄ν¬λνΈμ μ 곡ν¨μΌλ‘μ¨ μ½λ μ¬μ¬μ©μ±, μ»΄ν¬λνΈ κ΅¬μ± λ° κ΄μ¬μ¬ λΆλ¦¬λ₯Ό μ΄μ§ν μ μμ΅λλ€. ν μ΄ λ νλμ μ΄κ³ μ’ μ’ λ κ°λ¨ν λμμ μ 곡νμ§λ§, λ λ νλ‘μ νΉν λ κ±°μ μ½λλ λ λλ§ νλ‘μΈμ€μ λν μΈλ°ν μ μ΄κ° νμν μλ리μ€λ₯Ό λ€λ£° λ React κ°λ°μμ λ¬΄κΈ°κ³ μμ κ°λ ₯ν λκ΅¬λ‘ λ¨μ μμ΅λλ€.
λ λ νλ‘ ν¨ν΄μ μ΄μ κ³Ό λͺ¨λ² μ¬λ‘λ₯Ό μ΄ν΄ν¨μΌλ‘μ¨, λ€μν μ μΈκ³ μ¬μ©μλ₯Ό λ§μ‘±μν€λ κ²¬κ³ νκ³ μ μμ± μλ μ ν리μΌμ΄μ μ ꡬμΆνμ¬ μ¬λ¬ μ§μκ³Ό λ¬Ένμ κ±Έμ³ μΌκ΄λκ³ λ§€λ ₯μ μΈ μ¬μ©μ κ²½νμ 보μ₯ν μ μμ΅λλ€. ν΅μ¬μ νλ‘μ νΈμ νΉμ μꡬ μ¬νκ³Ό νμ μ λ¬Έ μ§μμ κΈ°λ°μΌλ‘ μ¬λ°λ₯Έ ν¨ν΄(λ λ νλ‘, HOC λλ ν )μ μ ννλ κ²μ λλ€. μν€ν μ² κ²°μ μ λ΄λ¦΄ λ νμ μ½λ κ°λ μ±, μ μ§λ³΄μμ± λ° μ±λ₯μ μ°μ μν΄μΌ νλ€λ μ μ κΈ°μ΅νμΈμ.